package com.ws.universal.tools.utils;


import android.util.Log;

import androidx.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * <pre>
 *     author: zt
 *     blog  : http://blankj.com
 *     time  : 2017/05/31
 *     desc  : Log相关工具类
 * </pre>
 */
public final class LogcatUtils {
    public static final int V = Log.VERBOSE;
    public static final int D = Log.DEBUG;
    public static final int I = Log.INFO;
    public static final int W = Log.WARN;
    public static final int E = Log.ERROR;
    public static final int A = Log.ASSERT;
    public static final int MAX_LEN = 3000000;
    public static final String NULL_TIPS = "Log with null object.";
    public static final String NULL = "null";
    public static final String ARGS = "args";
    private static final char[] T = new char[]{'V', 'D', 'I', 'W', 'E', 'A'};
    public static boolean sLogSwitch = true; // log总开关，默认开
    public static String sGlobalTag = "LogcatUtils"; // log标签
    public static int sConsoleFilter = V;    // log控制台过滤器

    public LogcatUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 设置日志开关 是否打印日志
     *
     * @param logSwitch
     * @return
     */
    public static void setLogSwitch(boolean logSwitch) {
        LogcatUtils.sLogSwitch = logSwitch;
    }

    /**
     * 设置日志TAG
     *
     * @param tag
     * @return
     */
    public static void setGlobalTag(final String tag) {
        LogcatUtils.sGlobalTag = tag;
    }

    public static void v(Object contents) {
        log(V, sGlobalTag, contents);
    }

    public static void v(String tag, Object... contents) {
        log(V, tag, contents);
    }

    public static void d(Object contents) {
        log(D, sGlobalTag, contents);
    }

    public static void d(String tag, Object... contents) {
        log(D, tag, contents);
    }

    public static void i(Object contents) {
        log(I, sGlobalTag, contents);
    }

    public static void i(String tag, Object... contents) {
        log(I, tag, contents);
    }

    public static void w(Object contents) {
        log(W, sGlobalTag, contents);
    }

    public static void w(String tag, Object... contents) {
        log(W, tag, contents);
    }

    public static void e(Object contents) {
        log(E, sGlobalTag, contents);
    }

    public static void e(String tag, Object... contents) {
        log(E, tag, contents);
    }

    public static void a(Object contents) {
        log(A, sGlobalTag, contents);
    }

    public static void a(String tag, Object... contents) {
        log(A, tag, contents);
    }

    private static void log(final int type, String tag, final Object... contents) {


        if (!sLogSwitch)
            return;
        int type_low = type & 0x0f, type_high = type & 0xf0;
        if (type_low < sConsoleFilter)
            return;
        final String[] tagAndHead = processTagAndHead(tag);
        String body = processBody(type_high, contents);

        print2Console(type_low, tagAndHead[0], tagAndHead[1] + body);

    }

    private static String[] processTagAndHead(String tag) {
        StackTraceElement targetElement = Thread.currentThread().getStackTrace()[5];
        String className = targetElement.getClassName();
        String[] classNameInfo = className.split("\\.");
        if (classNameInfo.length > 0) {
            className = classNameInfo[classNameInfo.length - 1];
        }
        if (className.contains("$")) {
            className = className.split("\\$")[0];
        }


        //        String head = new Formatter()
        //                .format("(%s.java:%d)",
        //                        className,
        //                        targetElement.getLineNumber())
        //                .toString();
        //        return new String[]{head, tag};
        return new String[]{tag, ""};
    }

    private static String processBody(int type, Object... contents) {
        String body = NULL_TIPS;
        if (contents != null) {
            Object object = contents[0];
            body = object == null ? NULL : object.toString();

        }
        return body;
    }

    private static void print2Console(final int type, String tag, String msg) {

        int len = msg.length();
        int countOfSub = len / MAX_LEN;
        if (countOfSub > 0) {
            print(type, tag, msg.substring(0, MAX_LEN));
            String sub;
            int index = MAX_LEN;
            for (int i = 1; i < countOfSub; i++) {
                sub = msg.substring(index, index + MAX_LEN);
                print(type, tag, sub);
                index += MAX_LEN;
            }
            sub = msg.substring(index, len);
            print(type, tag, sub);
        } else {
            print(type, tag, msg);
        }

    }

    private static void print(final int type, final String tag, String msg) {
        Log.println(type, tag, msg);
    }

    @IntDef({V, D, I, W, E, A})
    @Retention(RetentionPolicy.SOURCE)
    private @interface TYPE {
    }


}




